package ptij.vocoder.baseModel;

import ptij.vocoder.baseModel.common.Word32;

//////////////////////////////////////////////////////////////////////////
//// BasicOp
/** 

@author Ivan Jeukens
@version v 0.1 07/08/2003
*/
public class BasicOp  {

    public BasicOp() {
    }

    public static boolean Overflow = false;
    public static boolean Carry = false;
    
    public static final short saturate(int L_var1) {
        short var_out;

        if (L_var1 > 0X00007fff)
        {
            Overflow = true;
            var_out = Cnst.MAX_16;
        }
        else if (L_var1 < (int) 0xffff8000)
        {
            Overflow = true;
            var_out = Cnst.MIN_16;
        }
        else
        {
            Overflow = false;
            var_out = extract_l(L_var1);
        }

        return (var_out);
    }

    public static short add(short var1, short var2) {
        short var_out;
        int L_sum;

        L_sum = (int) var1 + var2;
        var_out = saturate(L_sum);

        return var_out;
    }

    public static short sub(short var1, short var2) {
        short var_out;
        int L_diff;

        L_diff = (int) var1 - var2;
        var_out = saturate(L_diff);

        return var_out;
    }

    public static final short abs_s(short var1) {
        short var_out;

        if (var1 == (short)0x8000)
        {
            var_out = Cnst.MAX_16;
        }
        else
        {
            if (var1 < 0)
            {
                var_out = (short) (-var1);
            }
            else
            {
                var_out = var1;
            }
        }
        return var_out;
    }
    
    public static final short shl(short var1, short var2) {
        short var_out;
        int result;

        if(var2 < 0)
        {
            var_out = shr(var1, (short) -var2);
        }
        else
        {
            result = (int) var1 * ((int) 1 << var2);
    
            if ((var2 > 15 && var1 != 0) || (result != (int)((short) result)))
            {
                Overflow = true;
                var_out = (var1 > 0) ? Cnst.MAX_16 : Cnst.MIN_16;
            }
            else
            {
                var_out = extract_l(result);
            }
        }
        return var_out;
    }
    
    public static final short shr(short var1, short var2) {
        short var_out;

        if(var2 < 0)
        {
            var_out = shl(var1, (short)(-var2));
        }
        else
        {
            if (var2 >= 15)
            {
                var_out = (var1 < 0) ? (short)-1 : (short)0;
            }
            else
            {
                if (var1 < 0)
                {
                    var_out = (short)~((~var1) >> var2);
                }
                else
                {
                    var_out = (short) (var1 >> var2);
                }
            }
        }

        return (var_out);
    }

    public static final short mult(short var1, short var2) {
        short var_out;
        int L_product;
    
        L_product = (int) var1 * (int) var2;
    
        L_product = (L_product & (int) 0xffff8000) >> 15;
    
        if((L_product & (int) 0x00010000) != 0) {
            L_product = L_product | (int) 0xffff0000;
        }
        var_out = saturate(L_product);

        return var_out;
    }
    
     public static final int L_mult(short var1, short var2) {
        int L_var_out;

        L_var_out = (int) var1 * (int) var2;

        if(L_var_out != (int) 0x40000000)
        {
            L_var_out *= 2;
        }
        else
        {
            Overflow = true;
            L_var_out = Cnst.MAX_32;
        }

        return (L_var_out);
    }

    public static final short negate(short var1) {
        short var_out;
        var_out = (var1 == Cnst.MIN_16) ? (short)Cnst.MAX_16 : (short)(-var1);

        return var_out;
    }

    public static short extract_h(int L_var1)
    {
        short var_out;

        var_out = (short) (L_var1 >> 16);
        return var_out;
    }

    public static short extract_l(int L_var1) {
        short var_out;
        var_out = (short) L_var1;
        return (var_out);
    }
    
    public static final short round(int L_var1) {
        short var_out;
        int L_rounded;

        L_rounded = L_add(L_var1, (int) 0x00008000);
        var_out = extract_h(L_rounded);

        return (var_out);
    }
    
    public static final int L_mac(int L_var3, short var1, short var2) {
        int L_var_out;
        int L_product;

        L_product = L_mult(var1, var2);
        L_var_out = L_add(L_var3, L_product);

        return L_var_out;
    }
    
    public static final int L_msu(int L_var3, short var1, short var2) {
        int L_var_out;
        int L_product;

        L_product = L_mult(var1, var2);
        L_var_out = L_sub(L_var3, L_product);

        return L_var_out;
    }
    
    public static final int L_macNs(int L_var3, short var1, short var2) {
        int L_var_out;

        L_var_out = L_mult(var1, var2);
        L_var_out = L_add_c(L_var3, L_var_out);

        return L_var_out;
    }
    
    public static int L_add(int L_var1, int L_var2) {
        int L_var_out;

        L_var_out = L_var1 + L_var2;

        if (((L_var1 ^ L_var2) & Cnst.MIN_32) == 0)
        {
            if (((L_var_out ^ L_var1) & Cnst.MIN_32) != 0)
            {
                L_var_out = (L_var1 < 0) ? Cnst.MIN_32 : Cnst.MAX_32;
                Overflow = true;
            }
        }
        return L_var_out;
    }
    
    public static int L_sub(int L_var1, int L_var2) {
        int L_var_out;

        L_var_out = L_var1 - L_var2;

        if (((L_var1 ^ L_var2) & Cnst.MIN_32) != 0)
        {
            if (((L_var_out ^ L_var1) & Cnst.MIN_32) != 0)
            {
                L_var_out = (L_var1 < 0L) ? Cnst.MIN_32 : Cnst.MAX_32;
                Overflow = true;
            }
        }

        return L_var_out;
    }

    public static final int L_add_c(int L_var1, int L_var2) {
        int L_var_out;
        int L_test;
        boolean carry_int = false;

        int carry = (Carry) ? 1 : 0;
        L_var_out = L_var1 + L_var2 + carry;

        L_test = L_var1 + L_var2;

        if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0))
        {
            Overflow = true;
            carry_int = false;
        }
        else
        {
            if ((L_var1 < 0) && (L_var2 < 0))
            {
                if (L_test >= 0)
                {
                    Overflow = true;
                    carry_int = true;
                }
                else
                {
                    Overflow = false;
                    carry_int = true;
                }
            }
            else
            {
                if (((L_var1 ^ L_var2) < 0) && (L_test >= 0))
                {
                    Overflow = false;
                    carry_int = true;
                }
                else
                {
                    Overflow = false;
                    carry_int = false;
                }
            }
        }

        if(Carry)
        {
            if (L_test == Cnst.MAX_32)
            {
                Overflow = true;
                Carry = carry_int;
            }
            else
            {
                if (L_test == (int) 0xFFFFFFFF)
                {
                    Carry = true;
                }
                else
                {
                    Carry = carry_int;
                }
            }
        }
        else
        {
            Carry = carry_int;
        }

        return L_var_out;
    }

    public static final int L_negate(int L_var1) {
        int L_var_out;

        L_var_out = (L_var1 == Cnst.MIN_32) ? Cnst.MAX_32 : -L_var1;

        return L_var_out;
    }
    
    public static final short mult_r(short var1, short var2) {
        short var_out;
        int L_product_arr;

        L_product_arr = (int) var1 * (int) var2;
        L_product_arr += (int) 0x00004000;
        L_product_arr &= (int) 0xffff8000;
        L_product_arr >>= 15;

        if((L_product_arr & (int) 0x00010000) != 0)
        {
            L_product_arr |= (int) 0xffff0000;
        }
        var_out = saturate(L_product_arr);

        return var_out;
    }

    public static final int L_shl(int L_var1, short var2) {
        int L_var_out = 0;
    
        if (var2 <= 0)
        {
            L_var_out = L_shr (L_var1, (short)(-var2));
        }
        else
        {
            for (; var2 > 0; var2--)
            {
                if (L_var1 > (int) 0X3fffffff)
                {
                    Overflow = true;
                    L_var_out = Cnst.MAX_32;
                    break;
                }
                else
                {
                    if (L_var1 < (int) 0xc0000000)
                    {
                        Overflow = true;
                        L_var_out = Cnst.MIN_32;
                        break;
                    }
                }
                L_var1 *= 2;
                L_var_out = L_var1;
            }
        }

        return L_var_out;
    }

    public static final int L_shr(int L_var1, short var2) {
        int L_var_out;
    
        if (var2 < 0)
        {
            L_var_out = L_shl(L_var1, (short)(-var2));
        }
        else
        {
            if (var2 >= 31)
            {
                L_var_out = (L_var1 < 0) ? -1 : 0;
            }
            else
            {
                if (L_var1 < 0)
                {
                    L_var_out = ~((~L_var1) >> var2);
                }
                else
                {
                    L_var_out = L_var1 >> var2;
                }
            }
        }
    
        return (L_var_out);
    }

    public static final short shr_r(short var1, short var2) {
        short var_out;
    
        if (var2 > 15)
        {
            var_out = 0;
        }
        else
        {
            var_out = shr(var1, var2);

            if (var2 > 0)
            {
                if ((var1 & ((short) 1 << (var2 - 1))) != 0)
                {
                    var_out++;
                }
            }
        }
    
        return (var_out);
    }
    
    public static final short mac_r(int L_var3, short var1, short var2) {
        short var_out;

        L_var3 = L_mac(L_var3, var1, var2);
        L_var3 = L_add(L_var3, (int) 0x00008000);
        var_out = extract_h(L_var3);

        return (var_out);
    }
    
    public static final short msu_r(int L_var3, short var1, short var2) {
        short var_out;

        L_var3 = L_msu(L_var3, var1, var2);
        L_var3 = L_add(L_var3, (int) 0x00008000);
        var_out = extract_h(L_var3);

        return (var_out);
    }
    
    public static final int L_deposit_h(short var1) {
        int L_var_out;
        L_var_out = (int) var1 << 16;

        return (L_var_out);
    }
    
    
    public static final int L_deposit_l(short var1) {
        int L_var_out;

        L_var_out = (int) var1;
        return L_var_out;
    }
    
    public static final int L_shr_r(int L_var1, short var2) {
        int L_var_out;
    
        if(var2 > 31)
        {
            L_var_out = 0;
        }
        else
        {
            L_var_out = L_shr(L_var1, var2);
    
            if (var2 > 0)
            {
                if ((L_var1 & ((int) 1 << (var2 - 1))) != 0)
                {
                    L_var_out++;
                }
            }
        }
    
        return (L_var_out);
    }
    
    public static final int L_abs(int L_var1) {
        int L_var_out;
    
        if (L_var1 == Cnst.MIN_32)
        {
            L_var_out = Cnst.MAX_32;
        }
        else
        {
            if (L_var1 < 0)
            {
                L_var_out = -L_var1;
            }
            else
            {
                L_var_out = L_var1;
            }
        }
        return (L_var_out);
    }
    
    public static final short norm_s(short var1) {
        short var_out;
    
        if(var1 == 0)
        {
            var_out = 0;
        }
        else
        {
            if (var1 == (short) 0xffff)
            {
                var_out = 15;
            }
            else
            {
                if (var1 < 0)
                {
                    var1 = (short)(~var1);
                }
                for (var_out = 0; var1 < 0x4000; var_out++)
                {
                    var1 <<= 1;
                }
            }
        }
        return (var_out);
    }

    public static final short div_s(short var1, short var2) {
        short var_out = 0;
        int iteration;
        int L_num;
        int L_denom;

        if (var1 == 0)
        {
            var_out = 0;
        }
        else
        {
            if (var1 == var2)
            {
                var_out = Cnst.MAX_16;
            }
            else
            {
                L_num = L_deposit_l(var1);
                L_denom = L_deposit_l(var2);
    
                for (iteration = 0; iteration < 15; iteration++)
                {
                    var_out <<= 1;
                    L_num <<= 1;
    
                    if (L_num >= L_denom)
                    {
                        L_num = L_sub (L_num, L_denom);
                        var_out = add(var_out, (short)1);
                    }
                }
            }
        }

        return (var_out);
    }

    public static final short norm_l(int L_var1) {
        short var_out;
    
        if (L_var1 == 0)
        {
            var_out = 0;
        }
        else
        {
            if (L_var1 == (int) 0xffffffff)
            {
                var_out = 31;
            }
            else
            {
                if (L_var1 < 0)
                {
                    L_var1 = ~L_var1;
                }
                for (var_out = 0; L_var1 < (int) 0x40000000; var_out++)
                {
                    L_var1 <<= 1;
                }
            }
        }
        return (var_out);
    }

    public static final void L_Extract(int L_32, Word32 hilo) {
        hilo.hi = extract_h (L_32);
        hilo.lo = extract_l (L_msu (L_shr (L_32, (short)1), hilo.hi, (short)16384));
        return;
    }

    public static final int L_Comp(short hi, short lo) {
        int L_32;
        L_32 = L_deposit_h(hi);
        return (L_mac (L_32, lo, (short)1));
    }

    public static final int Mpy_32(short hi1, short lo1, short hi2, short lo2) {
        int L_32;

        L_32 = L_mult (hi1, hi2);
        L_32 = L_mac (L_32, mult (hi1, lo2), (short)1);
        L_32 = L_mac (L_32, mult (lo1, hi2), (short)1);

        return (L_32);
    }

    public static final int Mpy_32_16(short hi, short lo, short n) {
        int L_32;

        L_32 = L_mult(hi, n);
        L_32 = L_mac(L_32, mult (lo, n), (short)1);

        return (L_32);
    }

    public static final int Div_32(int L_num, short denom_hi, short denom_lo) {
        short approx;
        int L_32;
    
        approx = div_s((short) 0x3fff, denom_hi);

        L_32 = Mpy_32_16(denom_hi, denom_lo, approx);
        
        L_32 = L_sub ((int) 0x7fffffff, L_32);

        Word32 w32 = new Word32();
        w32.hi = 0;
        w32.lo = 0;
        L_Extract(L_32, w32);

        L_32 = Mpy_32_16(w32.hi, w32.lo, approx);

        L_Extract (L_32, w32);

        Word32 nw32 = new Word32();
        L_Extract (L_num, nw32);
        L_32 = Mpy_32 (nw32.hi, nw32.lo, w32.hi, w32.lo);
        L_32 = L_shl(L_32, (short)2);

        return (L_32);
    }

    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////



    ///////////////////////////////////////////////////////////////////
    ////                         private methods                   ////
   

    ///////////////////////////////////////////////////////////////////
    ////                         private variables                 ////

}
